home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / WINGs / wwindow.c < prev   
Encoding:
C/C++ Source or Header  |  1999-10-09  |  16.5 KB  |  724 lines

  1.  
  2. #include <X11/Xmd.h>
  3.  
  4. #include "WINGsP.h"
  5.  
  6. #include <X11/Xatom.h>
  7.  
  8.  
  9. typedef struct W_Window {
  10.     W_Class widgetClass;
  11.     W_View *view;
  12.     
  13.     struct W_Window *nextPtr;           /* next in the window list */
  14.  
  15.     struct W_Window *owner;
  16.     
  17.     char *title;
  18.  
  19.     WMPixmap *miniImage;           /* miniwindow */
  20.     char *miniTitle;
  21.  
  22.     char *wname;
  23.  
  24.     WMSize resizeIncrement;
  25.     WMSize baseSize;
  26.     WMSize minSize;
  27.     WMSize maxSize;
  28.  
  29.     WMPoint upos;
  30.     WMSize usize;
  31.  
  32.     WMAction *closeAction;
  33.     void *closeData;
  34.     
  35.     int level;
  36.  
  37.     struct {
  38.     unsigned style:4;
  39.     unsigned configured:1;
  40.     unsigned documentEdited:1;
  41.  
  42.     unsigned upos_set:1;
  43.     } flags;
  44. } _Window;
  45.  
  46.  
  47.  
  48. typedef struct {
  49.     CARD32 flags;
  50.     CARD32 window_style;
  51.     CARD32 window_level;
  52.     CARD32 reserved;
  53.     Pixmap miniaturize_pixmap;           /* pixmap for miniaturize button */
  54.     Pixmap close_pixmap;           /* pixmap for close button */
  55.     Pixmap miniaturize_mask;           /* miniaturize pixmap mask */
  56.     Pixmap close_mask;               /* close pixmap mask */
  57.     CARD32 extra_flags;
  58. } GNUstepWMAttributes;
  59.  
  60. #define GSWindowStyleAttr     (1<<0)
  61. #define GSWindowLevelAttr     (1<<1)
  62. #define GSMiniaturizePixmapAttr    (1<<3)
  63. #define GSClosePixmapAttr    (1<<4)
  64. #define GSMiniaturizeMaskAttr    (1<<5)
  65. #define GSCloseMaskAttr        (1<<6)
  66. #define GSExtraFlagsAttr    (1<<7)
  67.  
  68. /* extra flags */
  69. #define GSDocumentEditedFlag    (1<<0)
  70. #define GSNoApplicationIconFlag    (1<<5)
  71.  
  72. #define WMFHideOtherApplications    10
  73. #define WMFHideApplication        12
  74.  
  75.  
  76.  
  77. static void willResizeWindow(W_ViewDelegate *, WMView *, unsigned*, unsigned*);
  78.  
  79. struct W_ViewDelegate _WindowViewDelegate = {
  80.     NULL,
  81.     NULL,
  82.     NULL,
  83.     NULL,
  84.     willResizeWindow
  85. };
  86.  
  87.  
  88. #define DEFAULT_WIDTH    400
  89. #define DEFAULT_HEIGHT    180
  90. #define DEFAULT_TITLE    ""
  91.  
  92.  
  93. static void destroyWindow(_Window *win);
  94.  
  95. static void handleEvents();
  96.  
  97. static void realizeWindow();
  98.  
  99. static void 
  100. realizeObserver(void *self, WMNotification *not)
  101. {
  102.     realizeWindow(self);
  103. }
  104.  
  105.  
  106. WMWindow*
  107. WMCreatePanelWithStyleForWindow(WMWindow *owner, char *name, int style)
  108. {
  109.     WMWindow *win;
  110.     
  111.     win = WMCreateWindowWithStyle(owner->view->screen, name, style);
  112.     win->owner = owner;
  113.  
  114.     return win;
  115. }
  116.  
  117.  
  118.  
  119. WMWindow*
  120. WMCreatePanelForWindow(WMWindow *owner, char *name)
  121. {    
  122.     return WMCreatePanelWithStyleForWindow(owner, name, 
  123.                        WMTitledWindowMask
  124.                        |WMClosableWindowMask
  125.                        |WMResizableWindowMask);
  126. }
  127.  
  128.  
  129. void
  130. WMChangePanelOwner(WMWindow *win, WMWindow *newOwner)
  131. {
  132.     win->owner = newOwner;
  133.     
  134.     if (win->view->flags.realized && newOwner) {
  135.     XSetTransientForHint(win->view->screen->display, win->view->window,
  136.                  newOwner->view->window);
  137.     }
  138. }
  139.  
  140.  
  141.  
  142. WMWindow*
  143. WMCreateWindow(WMScreen *screen, char *name)
  144. {
  145.     return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
  146.                    |WMClosableWindowMask
  147.                    |WMMiniaturizableWindowMask
  148.                    |WMResizableWindowMask);
  149. }
  150.  
  151.  
  152.  
  153. WMWindow*
  154. WMCreateWindowWithStyle(WMScreen *screen, char *name, int style)
  155. {
  156.     _Window *win;
  157.  
  158.     win = wmalloc(sizeof(_Window));
  159.     memset(win, 0, sizeof(_Window));
  160.  
  161.     win->widgetClass = WC_Window;
  162.  
  163.     win->view = W_CreateTopView(screen);
  164.     if (!win->view) {
  165.     wfree(win);
  166.     return NULL;
  167.     }
  168.     win->view->self = win;
  169.  
  170.     win->view->delegate = &_WindowViewDelegate;
  171.  
  172.     win->wname = wstrdup(name);
  173.  
  174.     /* add to the window list of the screen (application) */
  175.     win->nextPtr = screen->windowList;
  176.     screen->windowList = win;
  177.  
  178.     WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
  179.              |ClientMessageMask|FocusChangeMask, 
  180.              handleEvents, win);
  181.  
  182.     W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
  183.  
  184.     WMAddNotificationObserver(realizeObserver, win,
  185.                   WMViewRealizedNotification, win->view);
  186.  
  187.     win->flags.style = style;
  188.  
  189.     win->level = WMNormalWindowLevel;
  190.  
  191.     /* kluge. Find a better solution */
  192.     W_SetFocusOfTopLevel(win->view, win->view);
  193.  
  194.     return win;
  195. }
  196.  
  197.  
  198. void
  199. WMSetWindowTitle(WMWindow *win, char *title)
  200. {
  201.     XTextProperty property;
  202.     int result;
  203.  
  204.     if (win->title!=NULL)
  205.     wfree(win->title);
  206.     if (title!=NULL)
  207.     win->title = wstrdup(title);
  208.     else
  209.     win->title = NULL;
  210.  
  211.     if (win->view->flags.realized) {
  212.     result = XmbTextListToTextProperty (win->view->screen->display,
  213.                         &title, 1, XStdICCTextStyle,
  214.                         &property);
  215.     if (result == XNoMemory || result == XLocaleNotSupported) {
  216.         wwarning("window title conversion error... using STRING encoding");
  217.         XStoreName(win->view->screen->display, win->view->window, title);
  218.     } else {
  219.         XSetWMName(win->view->screen->display, win->view->window, &property);
  220.         if (property.value)
  221.             XFree(property.value);
  222.     }
  223.     }
  224. }
  225.  
  226.  
  227.  
  228.  
  229. void
  230. WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
  231. {
  232.     Atom *atoms = NULL;
  233.     Atom *newAtoms;
  234.     int count;
  235.     WMScreen *scr = win->view->screen;
  236.  
  237.     if (win->view->flags.realized) {
  238.     if (action && !win->closeAction) {
  239.         if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
  240.                 &count)) {
  241.         count = 0;
  242.         }
  243.         newAtoms = wmalloc((count+1)*sizeof(Atom));
  244.         if (count > 0)
  245.         memcpy(newAtoms, atoms, count*sizeof(Atom));
  246.         newAtoms[count++] = scr->deleteWindowAtom;
  247.         XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
  248.         if (atoms)
  249.         XFree(atoms);
  250.         wfree(newAtoms);
  251.     } else if (!action && win->closeAction) {
  252.         int i, ncount;
  253.         
  254.         if (XGetWMProtocols(scr->display, win->view->window, &atoms, 
  255.                  &count) && count>0) {
  256.         newAtoms = wmalloc((count-1)*sizeof(Atom));
  257.         ncount = 0;
  258.         for (i=0; i < count; i++) {
  259.             if (atoms[i]!=scr->deleteWindowAtom) {
  260.             newAtoms[i] = atoms[i];
  261.             ncount++;
  262.             }
  263.         }
  264.         XSetWMProtocols(scr->display, win->view->window, newAtoms, 
  265.                 ncount);
  266.         if (atoms)
  267.             XFree(atoms);
  268.         wfree(newAtoms);
  269.         }
  270.     }
  271.     }
  272.     win->closeAction = action;
  273.     win->closeData = clientData;    
  274. }
  275.  
  276.  
  277.  
  278. static void
  279. willResizeWindow(W_ViewDelegate *self, WMView *view,
  280.          unsigned *width, unsigned *height)
  281. {
  282.     WMWindow *win = (WMWindow*)view->self;
  283.  
  284.     if (win->minSize.width > 0 && win->minSize.height > 0) {
  285.     if (*width < win->minSize.width)
  286.         *width = win->minSize.width;
  287.     if (*height < win->minSize.height)
  288.         *height = win->minSize.height;
  289.     }
  290.     
  291.     if (win->maxSize.width > 0 && win->maxSize.height > 0) {
  292.     if (*width > win->maxSize.width)
  293.         *width = win->maxSize.width;
  294.     if (*height > win->maxSize.height)
  295.         *height = win->maxSize.height;
  296.     }
  297. }
  298.  
  299.  
  300. static void
  301. setSizeHints(WMWindow *win)
  302. {
  303.     XSizeHints *hints;
  304.  
  305.     hints = XAllocSizeHints();
  306.     if (!hints) {
  307.     wwarning("could not allocate memory for window size hints");
  308.     return;
  309.     }
  310.  
  311.     hints->flags = 0;
  312.  
  313.     if (win->flags.upos_set) {
  314.     hints->flags |= PPosition;
  315.     hints->x = win->upos.x;
  316.     hints->y = win->upos.y;
  317.     }
  318.     if (win->usize.width>0 && win->usize.height>0) {
  319.     hints->flags |= PSize;
  320.     hints->width = win->usize.width;
  321.     hints->height = win->usize.height;
  322.     }
  323.     if (win->minSize.width>0 && win->minSize.height>0) {
  324.     hints->flags |= PMinSize;
  325.     hints->min_width = win->minSize.width;
  326.     hints->min_height = win->minSize.height;
  327.     }
  328.     if (win->maxSize.width>0 && win->maxSize.height>0) {
  329.     hints->flags |= PMaxSize;
  330.     hints->max_width = win->maxSize.width;
  331.     hints->max_height = win->maxSize.height;
  332.     }
  333.     if (win->baseSize.width>0 && win->baseSize.height>0) {
  334.     hints->flags |= PBaseSize;
  335.     hints->base_width = win->baseSize.width;
  336.     hints->base_height = win->baseSize.height;
  337.     }
  338.     if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
  339.     hints->flags |= PResizeInc;
  340.     hints->width_inc = win->resizeIncrement.width;
  341.     hints->height_inc = win->resizeIncrement.height;
  342.     }
  343.     
  344.     if (hints->flags) {
  345.     XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
  346.     }
  347.     XFree(hints);
  348. }
  349.  
  350.  
  351.  
  352. static void
  353. writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
  354. {
  355.     unsigned long data[9];
  356.  
  357.     /* handle idiot compilers where array of CARD32 != struct of CARD32 */
  358.     data[0] = attr->flags;
  359.     data[1] = attr->window_style;
  360.     data[2] = attr->window_level;
  361.     data[3] = 0;               /* reserved */
  362.     /* The X protocol says XIDs are 32bit */
  363.     data[4] = attr->miniaturize_pixmap;
  364.     data[5] = attr->close_pixmap;
  365.     data[6] = attr->miniaturize_mask;
  366.     data[7] = attr->close_mask;
  367.     data[8] = attr->extra_flags;
  368.     XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
  369.             32, PropModeReplace,  (unsigned char *)data, 9);
  370. }
  371.  
  372.  
  373. static void
  374. setWindowMakerHints(WMWindow *win)
  375. {
  376.     GNUstepWMAttributes attribs;
  377.     WMScreen *scr = WMWidgetScreen(win);
  378.     
  379.     memset(&attribs, 0, sizeof(GNUstepWMAttributes));
  380.     attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
  381.     attribs.window_style = win->flags.style;
  382.     attribs.window_level = win->level;
  383.     if (win->flags.documentEdited)
  384.     attribs.extra_flags = GSDocumentEditedFlag;
  385.     else
  386.     attribs.extra_flags = 0;
  387.  
  388.     writeGNUstepWMAttr(scr, win->view->window, &attribs);
  389. }
  390.  
  391.  
  392. static void 
  393. realizeWindow(WMWindow *win)
  394. {
  395.     XWMHints *hints;
  396.     XClassHint *classHint;
  397.     WMScreen *scr = win->view->screen;
  398.     Atom atoms[4];
  399.     int count;
  400.  
  401.     classHint = XAllocClassHint();
  402.     classHint->res_name = win->wname;
  403.     classHint->res_class = WMGetApplicationName();
  404.     XSetClassHint(scr->display, win->view->window, classHint);
  405.     XFree(classHint);
  406.  
  407.     hints = XAllocWMHints();
  408.     hints->flags = 0;
  409.     if (!scr->aflags.simpleApplication) {
  410.     hints->flags |= WindowGroupHint;
  411.     hints->window_group = scr->groupLeader;
  412.     }
  413.     if (win->miniImage) {
  414.     hints->flags |= IconPixmapHint;
  415.     hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
  416.     hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
  417.     if (hints->icon_mask != None) {
  418.         hints->flags |= IconMaskHint;
  419.     }
  420.     }
  421.     if (hints->flags != 0)
  422.     XSetWMHints(scr->display, win->view->window, hints);
  423.     XFree(hints);
  424.  
  425.     count = 0;
  426.     if (win->closeAction) {
  427.     atoms[count++] = scr->deleteWindowAtom;
  428.     }
  429.  
  430.     if (count>0)
  431.     XSetWMProtocols(scr->display, win->view->window, atoms, count);
  432.  
  433.     if (win->title || win->miniTitle)
  434.     XmbSetWMProperties(scr->display, win->view->window, win->title, 
  435.                win->miniTitle, NULL, 0, NULL, NULL, NULL);
  436.     
  437.     setWindowMakerHints(win);
  438.  
  439.     setSizeHints(win);
  440.  
  441.     if (win->owner) {
  442.     XSetTransientForHint(scr->display, win->view->window,
  443.                  win->owner->view->window);
  444.     }
  445. }
  446.  
  447.  
  448.  
  449. void
  450. WMSetWindowInitialPosition(WMWindow *win, int x, int y)
  451. {
  452.     win->flags.upos_set = 1;
  453.     win->upos.x = x;
  454.     win->upos.y = y;
  455.     if (win->view->flags.realized)
  456.         setSizeHints(win);
  457.     WMMoveWidget(win, x, y);
  458. }
  459.  
  460.  
  461.  
  462. void
  463. WMSetWindowInitialSize(WMWindow *win, unsigned width, unsigned height)
  464. {
  465.     win->usize.width = width;
  466.     win->usize.height = height;
  467.     if (win->view->flags.realized)
  468.         setSizeHints(win);
  469.     WMResizeWidget(win, width, height);
  470. }
  471.  
  472.  
  473. void
  474. WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
  475. {
  476.     win->minSize.width = width;
  477.     win->minSize.height = height;
  478.     if (win->view->flags.realized)
  479.     setSizeHints(win);
  480. }
  481.  
  482.  
  483.  
  484. void
  485. WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
  486. {
  487.     win->maxSize.width = width;
  488.     win->maxSize.height = height;
  489.     if (win->view->flags.realized)
  490.     setSizeHints(win);
  491. }
  492.  
  493.  
  494. void
  495. WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
  496. {
  497.     /* TODO: validate sizes */
  498.     win->baseSize.width = width;
  499.     win->baseSize.height = height;
  500.     if (win->view->flags.realized)
  501.     setSizeHints(win);
  502. }
  503.  
  504.  
  505. void
  506. WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
  507. {
  508.     win->resizeIncrement.width = wIncr;
  509.     win->resizeIncrement.height = hIncr;
  510.     if (win->view->flags.realized)
  511.     setSizeHints(win);
  512. }
  513.  
  514.  
  515. void
  516. WMSetWindowLevel(WMWindow *win, int level)
  517. {
  518.     win->level = level;
  519.     if (win->view->flags.realized)
  520.     setWindowMakerHints(win);
  521. }
  522.  
  523.  
  524. void
  525. WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
  526. {
  527.     if (win->flags.documentEdited != flag) {
  528.     win->flags.documentEdited = flag;
  529.     if (win->view->flags.realized)
  530.         setWindowMakerHints(win);
  531.     }
  532. }
  533.  
  534.  
  535. void
  536. WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
  537. {
  538.     if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
  539.     if (win->miniImage)
  540.         WMReleasePixmap(win->miniImage);
  541.  
  542.     if (pixmap)
  543.         win->miniImage = WMRetainPixmap(pixmap);
  544.     else
  545.         win->miniImage = NULL;
  546.  
  547.     if (win->view->flags.realized) {
  548.         XWMHints *hints;
  549.         
  550.         hints = XGetWMHints(win->view->screen->display, win->view->window);
  551.         if (!hints) {
  552.         hints = XAllocWMHints();
  553.         if (!hints) {
  554.             wwarning("could not allocate memory for WM hints");
  555.             return;
  556.         }
  557.         hints->flags = 0;
  558.         }
  559.         if (pixmap) {
  560.         hints->flags |= IconPixmapHint;
  561.         hints->icon_pixmap = WMGetPixmapXID(pixmap);
  562.         hints->icon_mask = WMGetPixmapMaskXID(pixmap);
  563.         if (hints->icon_mask != None) {
  564.             hints->flags |= IconMaskHint;
  565.         }
  566.         }
  567.         XSetWMHints(win->view->screen->display, win->view->window, hints);
  568.         XFree(hints);
  569.     }
  570.     }
  571. }
  572.  
  573.  
  574. void
  575. WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
  576. {
  577.     XTextProperty property;
  578.     int result;
  579.  
  580.     if ((win->miniTitle && !title) || (!win->miniTitle && title)
  581.     || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
  582.     if (win->miniTitle)
  583.         wfree(win->miniTitle);
  584.     
  585.     if (title)
  586.         win->miniTitle = wstrdup(title);
  587.     else
  588.         win->miniTitle = NULL;
  589.  
  590.     if (win->view->flags.realized) {
  591.         result = XmbTextListToTextProperty (win->view->screen->display,
  592.                         &title, 1, XStdICCTextStyle,
  593.                         &property);
  594.         if (result == XNoMemory || result == XLocaleNotSupported) {
  595.         wwarning("icon title conversion error..using STRING encoding");
  596.         XSetIconName(win->view->screen->display, win->view->window,
  597.                  title);
  598.         } else {
  599.         XSetWMIconName(win->view->screen->display, win->view->window,
  600.                    &property);
  601.         if (property.value)
  602.             XFree(property.value);
  603.         }
  604.     }
  605.     }
  606. }
  607.  
  608.  
  609. void
  610. WMCloseWindow(WMWindow *win)
  611. {
  612.     WMUnmapWidget(win);
  613.     /* withdraw the window */
  614.     if (win->view->flags.realized)
  615.     XWithdrawWindow(win->view->screen->display, win->view->window,
  616.             win->view->screen->screen);
  617. }
  618.  
  619.  
  620. static void
  621. handleEvents(XEvent *event, void *clientData)
  622. {
  623.     _Window *win = (_Window*)clientData;
  624.     W_View *view = win->view;
  625.     
  626.     
  627.     switch (event->type) {
  628.      case ClientMessage:
  629.     if (event->xclient.message_type == win->view->screen->protocolsAtom
  630.         && event->xclient.format == 32 
  631.         && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
  632.         
  633.         if (win->closeAction) {
  634.         (*win->closeAction)(win, win->closeData);
  635.         }
  636.     }
  637.     break;
  638.  
  639.      case UnmapNotify:
  640.     WMUnmapWidget(win);
  641.     break;
  642.  
  643.      case DestroyNotify:
  644.     destroyWindow(win);
  645.     break;
  646.     
  647.      case ConfigureNotify:
  648.     if (event->xconfigure.width != view->size.width
  649.         || event->xconfigure.height != view->size.height) {
  650.  
  651.         view->size.width = event->xconfigure.width;
  652.         view->size.height = event->xconfigure.height;
  653.  
  654.         if (view->flags.notifySizeChanged) {
  655.         WMPostNotificationName(WMViewSizeDidChangeNotification,
  656.                        view, NULL);
  657.         }
  658.     }
  659.     if (event->xconfigure.x != view->pos.x
  660.         || event->xconfigure.y != view->pos.y) {
  661.  
  662.         if (event->xconfigure.send_event) {
  663.         view->pos.x = event->xconfigure.x;
  664.         view->pos.y = event->xconfigure.y;
  665.         } else {
  666.         Window foo;
  667.  
  668.         XTranslateCoordinates(view->screen->display,
  669.                       view->window, view->screen->rootWin,
  670.                       event->xconfigure.x, event->xconfigure.y,
  671.                       &view->pos.x, &view->pos.y, &foo);
  672.         }
  673.     }
  674.     break;
  675.     }
  676. }
  677.  
  678.  
  679.  
  680.  
  681. static void
  682. destroyWindow(_Window *win)
  683. {
  684.     WMScreen *scr = win->view->screen;
  685.  
  686.     WMRemoveNotificationObserver(win);
  687.     
  688.     if (scr->windowList == win) {
  689.     scr->windowList = scr->windowList->nextPtr;
  690.     } else {
  691.     WMWindow *ptr;
  692.     ptr = scr->windowList;
  693.     
  694.     if (ptr) {
  695.         while (ptr->nextPtr) {
  696.         if (ptr->nextPtr==win) {
  697.             ptr->nextPtr = ptr->nextPtr->nextPtr;
  698.             break;
  699.         }
  700.         ptr = ptr->nextPtr;
  701.         }
  702.     }
  703.     }
  704.  
  705.     if (win->title) {
  706.     wfree(win->title);
  707.     }
  708.     
  709.     if (win->miniTitle) {
  710.     wfree(win->miniTitle);
  711.     }
  712.     
  713.     if (win->miniImage) {
  714.     WMReleasePixmap(win->miniImage);
  715.     }
  716.     
  717.     if (win->wname)
  718.     wfree(win->wname);
  719.  
  720.     wfree(win);
  721. }
  722.  
  723.  
  724.